/***************************************************************************
*   Copyright (C) 2010-2011 by swkyer <swkyer@gmail.com>                  *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
#ifndef __EXECUTION_H__
#define __EXECUTION_H__

#include "Ejtag.h"


#define MIPS32_VRAM_SIZE                    (4*1024)


#define MIPS32_FASTDATA_BASE				0xFF200000
#define MIPS32_FASTDATA_SIZE				0x00000010

#define MIPS32_DMSEG_BASEADDRESS			0xFF200200
#define MIPS32_DMSEG_RAM_BEGIN				0xFF2F0000

#define MIPS32_VIRTUAL_RAM_START			0xFF2F0000
#define MIPS32_VIRTUAL_RAM_SIZE				MIPS32_VRAM_SIZE	/* 0xFF2F0000 - 0xFF2F1000, 4K Bytes */

#define MIPS32_VIRTUAL_STACK_ADDR			0xFF2FFFFC

#define MIPS32_REGISTER_LOCATION			0xFF2FFE00
#define MIPS32_NUM_DEBUG_REGISTERS			38

#define MIPS32_CP0_REG_LOCATION				0xFF2FFF28
#define MIPS32_NUM_DEBUG_CP0_REG			16

#define MIPS32_ARG0_ADDR    				0xFF2FFD00
#define MIPS32_ARG1_ADDR					0xFF2FFD04
#define MIPS32_ARG2_ADDR                    0xFF2FFD08
#define MIPS32_ARG3_ADDR                    0xFF2FFD0C

#define MIPS32_INST_BKPT_STATUS				0xFF301000
#define MIPS32_INST_BKPT_ADDR(X)			(0xFF301100 + ((X) * 0x100))
#define MIPS32_INST_BKPT_ADDR_MSK(X)		(0xFF301108 + ((X) * 0x100))
#define MIPS32_INST_BKPT_ASID(X)			(0xFF301110 + ((X) * 0x100))
#define MIPS32_INST_BKPT_CONTROL(X)			(0xFF301118 + ((X) * 0x100))

#define MIPS32_DATA_BKPT_STATUS				0xFF302000
#define MIPS32_DATA_BKPT_ADDR(X)			(0xFF302100 + ((X) * 0x100))
#define MIPS32_DATA_BKPT_ADDR_MSK(X)		(0xFF302108 + ((X) * 0x100))
#define MIPS32_DATA_BKPT_ASID(X)			(0xFF302110 + ((X) * 0x100))
#define MIPS32_DATA_BKPT_CONTROL(X)			(0xFF302118 + ((X) * 0x100))
#define MIPS32_DATA_BKPT_VALUE(X)			(0xFF302120 + ((X) * 0x100))
#define MIPS32_DATA_BKPT_VALUEHI(X)			(0xFF302124 + ((X) * 0x100))



#define MIPS32_DEBUG_DBD			        (1<<31)
#define MIPS32_DEBUG_DM				        (1<<30)
#define MIPS32_DEBUG_NODCR			        (1<<29)
#define MIPS32_DEBUG_LSNM			        (1<<28)
#define MIPS32_DEBUG_DOZE			        (1<<27)
#define MIPS32_DEBUG_HALT			        (1<<26)
#define MIPS32_DEBUG_COUNTDM		        (1<<25)
#define MIPS32_DEBUG_IBUSEP			        (1<<24)
#define MIPS32_DEBUG_MCHECKP		        (1<<23)
#define MIPS32_DEBUG_CACHEEP		        (1<<22)
#define MIPS32_DEBUG_DBUSEP			        (1<<21)
#define MIPS32_DEBUG_IEXI			        (1<<20)
#define MIPS32_DEBUG_DDBSIMPR		        (1<<19)
#define MIPS32_DEBUG_DDBLIMPR		        (1<<18)
#define MIPS32_DEBUG_EJTAGVER		        (0x03<<15)
#define MIPS32_DEBUG_DEXCCODE		        (0x1F<<10)
#define MIPS32_DEBUG_NOSST			        (1<<9)
#define MIPS32_DEBUG_SST			        (1<<8)
#define MIPS32_DEBUG_OFFLINE		        (1<<7)
#define MIPS32_DEBUG_DINT			        (1<<5)
#define MIPS32_DEBUG_DIB			        (1<<4)
#define MIPS32_DEBUG_DDBS			        (1<<3)
#define MIPS32_DEBUG_DDBL			        (1<<2)
#define MIPS32_DEBUG_DBP			        (1<<1)
#define MIPS32_DEBUG_DSS			        (1<<0)


#define MIPS32_DBGEXCEP_MCHECK		        24
#define MIPS32_DBGEXCEP_ADEL		        4
#define MIPS32_DBGEXCEP_ADES		        5
#define MIPS32_DBGEXCEP_TLBL		        2
#define MIPS32_DBGEXCEP_TLBS		        3
#define MIPS32_DBGEXCEP_CACHEERR	        30
#define MIPS32_DBGEXCEP_IBE			        6
#define MIPS32_DBGEXCEP_DBE			        7


#define MIPS32_EJTAG_DCR_ENM		        (1<<29)
#define MIPS32_EJTAG_DCR_DATABRK	        (1<<17)
#define MIPS32_EJTAG_DCR_INSTBRK	        (1<<16)
#define MIPS32_EJTAG_DCR_PCS		        (1<<9)
#define MIPS32_EJTAG_DCR_PCR		        (0x07<<6)
#define MIPS32_EJTAG_DCR_INTE		        (1<<4)
#define MIPS32_EJTAG_DCR_NMIE		        (1<<3)
#define MIPS32_EJTAG_DCR_NMIpend	        (1<<2)
#define MIPS32_EJTAG_DCR_SRSTE		        (1<<1)
#define MIPS32_EJTAG_DCR_PROBEN		        (1<<0)

#define MIPS32_ECR_CPU_RESET_OCCURED	    (1 << 31)
#define MIPS32_ECR_ACCESS_SIZE			    (3 << 29)
#define MIPS32_ECR_ACCESS_BYTE			    (0 << 29)
#define MIPS32_ECR_ACCESS_HWORD			    (1 << 29)
#define MIPS32_ECR_ACCESS_WORD			    (2 << 29)
#define MIPS32_ECR_ACCESS_TRIPLE			(3 << 29)
#define MIPS32_ECR_DOZE					    (1 << 22)
#define MIPS32_ECR_HALT					    (1 << 21)
#define MIPS32_ECR_PERIPHERAL_RESET		    (1 << 20)
#define MIPS32_ECR_ACCESS_RW			    (1 << 19)
#define MIPS32_ECR_ACCESS_PENDING		    (1 << 18)
#define MIPS32_ECR_CPU_RESET			    (1 << 16)
#define MIPS32_ECR_PROBE_ENABLE			    (1 << 15)
#define MIPS32_ECR_PROBE_VECTOR			    (1 << 14)
#define MIPS32_ECR_EJTAG_BREAK			    (1 << 12)
#define MIPS32_ECR_IN_DEBUG_MODE		    (1 << 3)
#define MIPS32_ECR_SST					    (1 << 8)


typedef struct __mips32_exec_context
{
    void *pmips32;

    ubase_t reg_arg0;
    ubase_t reg_arg1;
    ubase_t reg_arg2;
    ubase_t reg_arg3;

    ubase_t vram[MIPS32_VRAM_SIZE/sizeof(ubase_t)];
} mips32_exec_context_t;


int mips32_exec_init(mips32_exec_context_t *pexec, void *pmips32);
int mips32_exec_exit(mips32_exec_context_t *pexec);
ubase_t mips32_get_ecr(ejtag_t *pejtag);
int mips32_exec_microcode(mips32_exec_context_t *pexec, const ubase_t *pcodes);


#endif /* end of __EXECUTION_H__ */
